package com.example.demo.Controller.User;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.ServiceImpl.User.UserServiceImpl;
import com.example.demo.Entity.User.User;
import com.example.demo.Utils.JWTUtils.JWTUtils;
import com.example.demo.Utils.Result.R;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RestController
@CrossOrigin(origins = "*")
@RequestMapping("/user")
@Tag(name = "UserController", description = "UserController 相关接口")
public class UserController {

    @Resource
    private UserServiceImpl userService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @PostMapping
    @Operation(summary = "保存或更新 User 信息", description = "根据传入的 User 对象保存或更新信息")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "保存或更新成功", content = @Content(schema = @Schema(implementation = Boolean.class)))
    })
    public Boolean save(@RequestBody User user) {
// 保存或更新数据后，删除相关缓存
        redisTemplate.delete("user:all");
        return userService.saveOrUpdate(user);
    }

    @DeleteMapping("/{id}")
    @Operation(summary = "根据 ID 删除 User 信息", description = "根据传入的 ID 删除对应的 User 信息")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "删除成功", content = @Content(schema = @Schema(implementation = Boolean.class)))
    })
    public Boolean delete(@PathVariable(value = "id") Integer id) {
// 删除数据后，删除相关缓存
        redisTemplate.delete("user:all");
        redisTemplate.delete("user:id:" + id);
        return userService.removeById(id);
    }

    @GetMapping
    @Operation(summary = "获取所有 User 信息", description = "获取所有 User 的列表信息")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "获取成功", content = @Content(schema = @Schema(implementation = R.class)))
    })
    public R findAll() {
        String key = "user:all";
        @SuppressWarnings("unchecked")
        List<User> userList = (List<User>) redisTemplate.opsForValue().get(key);
        if (userList == null) {
            userList = userService.list();
            redisTemplate.opsForValue().set(key, userList, 60, TimeUnit.MINUTES);
        }
        return R.ok().put("userList", userList);
    }

    @GetMapping("/{id}")
    @Operation(summary = "根据 ID 获取 User 信息", description = "根据传入的 ID 获取对应的 User 信息")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "获取成功", content = @Content(schema = @Schema(implementation = R.class)))
    })
    public R findOne(@PathVariable(value = "id") Integer id) {
        String key = "user:id:" + id;
        User user = (User) redisTemplate.opsForValue().get(key);
        if (user == null) {
            user = userService.getById(id);
            if (user != null) {
                redisTemplate.opsForValue().set(key, user, 60, TimeUnit.MINUTES);
            }
        }
        return R.ok().put("user", user);
    }

    @GetMapping("/page")
    @Operation(summary = "分页获取 User 信息", description = "根据传入的页码和每页数量分页获取 User 信息")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "获取成功", content = @Content(schema = @Schema(implementation = R.class)))
    })
    @Parameter(name = "pageNum", in = ParameterIn.QUERY, description = "页码", required = true)
    @Parameter(name = "pageSize", in = ParameterIn.QUERY, description = "每页数量", required = true)
    public R findPage(@RequestParam(value = "pageNum") Integer pageNum,
                      @RequestParam(value = "pageSize") Integer pageSize) {
        String key = "user:page:" + pageNum + ":" + pageSize;
        @SuppressWarnings("unchecked")
        Page<User> userPage = (Page<User>) redisTemplate.opsForValue().get(key);
        if (userPage == null) {
            userPage = userService.page(new Page<>(pageNum, pageSize));
            redisTemplate.opsForValue().set(key, userPage, 60, TimeUnit.MINUTES);
        }
        return R.ok().put("userPage", userPage);
    }

    @PostMapping("/getToken")
    @Transactional(rollbackFor = Exception.class)
    @Operation(summary = "根据用户名返回token", description = "常用于登陆后逻辑")
    public R Login(@RequestParam String username) {
        LambdaQueryWrapper<User> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(User::getUsername, username);
        User users = userService.getOne(queryWrapper);
        if (users == null) {
            return R.error();
        }
        users.setLastLoginTime(new Date());
        userService.updateById(users);
        Map<String, String> payload = new HashMap<>();
        payload.put("id", String.valueOf(users.getUserId()));
        payload.put("role", users.getRole());
        return R.ok().put("token", JWTUtils.getToken(payload));
    }

    @PostMapping("/logout")
    @Operation(summary = "用户退出登录", description = "用户退出登录")
    public R logout(HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        JWTUtils.invalidateToken(token);
        return R.ok();
    }
}